/* *********************************************************************************  
 *   This file is part of GeometryPlayground.
 *
 *   GeometryPlayground is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   GeometryPlayground is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with GeometryPlayground.  If not, see <http://www.gnu.org/licenses/>.
 **********************************************************************************/
 
import java.awt.Canvas;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.util.LinkedList;

import javax.swing.event.ChangeListener;

class GeoCanvas extends Canvas implements MouseListener,
MouseMotionListener/*,MouseWheelListener,KeyListener*/{
	protected static int SZ= GeoPlayground.CANVASSIZE/2;
	private final int BISECTOR=GeoConstruct.BISECTOR,
	SEGMENT=GeoConstruct.SEGMENT,
	PERP=GeoConstruct.PERP,
	LINE=GeoConstruct.LINE,
	CIRCLE=GeoConstruct.CIRCLE,
	POINT=GeoConstruct.POINT,
	PTonLINE=GeoConstruct.PTonLINE,
	PTonCIRC=GeoConstruct.PTonCIRC,
	LINEintLINE0=GeoConstruct.LINEintLINE0,
	LINEintLINE1=GeoConstruct.LINEintLINE1,
	CIRCintLINE0=GeoConstruct.CIRCintLINE0,
	CIRCintLINE1=GeoConstruct.CIRCintLINE1,
	CIRCintCIRC00=GeoConstruct.CIRCintCIRC00,
	CIRCintCIRC01=GeoConstruct.CIRCintCIRC01,
	CIRCintCIRC10=GeoConstruct.CIRCintCIRC10,
	CIRCintCIRC11=GeoConstruct.CIRCintCIRC11,
	MIDPT=GeoConstruct.MIDPT,
	FIXedPT=GeoConstruct.FIXedPT,
	DISTANCE=GeoConstruct.DISTANCE,
	AREA=GeoConstruct.AREA,
	CIRCUMF=GeoConstruct.CIRCUMF,
	ANGLE=GeoConstruct.ANGLE,
	RATIO=GeoConstruct.RATIO;
	private boolean alreadyMoving=false;
	protected ChangeListener geometryListener;
	protected GeoMetry geometry=null;
	public LinkedList<GeoConstruct>list = new LinkedList<GeoConstruct>();
	protected LinkedList<GeoConstruct> clickedList =new LinkedList<GeoConstruct>();
	protected GeoConstruct potentialClick=null, lastPotential=null, fixedObject=null;
	protected double[]	vector1=  {0,0,0}, vector2={0,0,0},
	norm=     {0,0,0},  binorm={0,0,0},
	dragStart={0,0,0}, dragNow={0,0,0};
	GeoCanvas(){
		addMouseMotionListener(this);
		addMouseListener(this);
	}
	GeoCanvas(GeoMetry m){
		this();
		geometry=m;
	}

	public void paint(Graphics g) {
		if (GeoPlayground.canvas[GeoPlayground.tabbedPanePlane.getSelectedIndex()].getWidth()<500)
			for (int i=0;i<6;i++) GeoPlayground.tabbedPanePlane.setTitleAt(i,GeoPlayground.tabText[1][i]);
		else for (int i=0;i<6;i++) GeoPlayground.tabbedPanePlane.setTitleAt(i,GeoPlayground.tabText[0][i]);
		SZ=(GeoPlayground.getHght()-1)/2;
		geometry.drawModel(g, SZ);
		
/*	  int l=0;
      for (int i=0;i<list.size();i++) {
	  if (list.get(i).getShown()) {
	  g.setColor(new Color(127,127,255));
	  if (list.get(i).getType()<0) g.setColor(new Color(255,127,127));
	  else if (list.get(i).getType()==0) g.setColor(new Color(127,191,127));
	     //list.get(i).getXYZ(vector1);
	     //for (int j=0;j<3;j++) vector2[j]=0;
	     //if (i>0) list.get(i-1).getXYZ(vector2);
		 //double phi=MathEqns.chop(MathEqns.dotProduct(vector1,vector2));
	  if (list.get(i).getValid()) 
	  g.drawString(""+i+":"+MathEqns.chop(list.get(i).getX())+" "
	                 +MathEqns.chop(list.get(i).getY())+" "
					 +MathEqns.chop(list.get(i).getZ())+" , "+list.get(i).getSize()+" , "+list.get(i).getType(),
					                        5+SZ*(l/19),13+25*l-475*(l/19));
	  else g.drawString("----- ----- -----",5+SZ*(l/19),13+25*l-475*(l/19));
	  if (list.get(i).getValidNew())
	  g.drawString(""+i+":"+MathEqns.chop(list.get(i).getNewX())+" "
					 +MathEqns.chop(list.get(i).getNewY())+" "
					 +MathEqns.chop(list.get(i).getNewZ())+" "//+phi
					                       ,5+SZ*(l/19),25+25*l-475*(l/19));
	  else g.drawString("----- ----- -----",5+SZ*(l/19),25+25*l-475*(l/19));
	  g.drawString(""+GeoPlayground.whatToDo,2*SZ-15,2*SZ-15);
	  l++;//
	  }
	} //*/
		//g.setColor(Color.black);
		//if (potentialClick!=null) g.drawString(""+potentialClick.getID(),SZ,SZ);
		/*    if (GeoPlayground.whatToDo!=GeoPlayground.Move) 
	  for (int i=0;i<list.size();i++) {
		list.get(i).getXYZ(vector1);
		list.get(i).setNewXYZ(vector1);
	  }//*/
	  if (geometry.getScale()!=1.0) {
	    g.setColor(Color.black);
	    String textString=""+((int)MathEqns.chop(geometry.getScale()));
	    if (geometry.getScale()<1) textString="1/"+((int)MathEqns.chop(1/geometry.getScale()));
	    g.drawString("("+textString+")",5,15);
	  }
	  drawAllConstructs(g,false);		// draw the Constructs
	  switch (GeoPlayground.whatToDo){  // look at what the user is doing
		case GeoPlayground.Move:
			if (!clickedList.isEmpty()) drawAllConstructs(g,true);  
			else if (potentialClick!=null) {colorSet(g,potentialClick,true);potentialClick.draw(g,SZ,true);}
			else if (MathEqns.norm(dragStart,dragNow)>0)
				drawAllConstructs(g,true);
			break;
		default:
		case GeoPlayground.MeasureRatio:
		case GeoPlayground.MakeLines:
		case GeoPlayground.MakeSegment:
		case GeoPlayground.MakeCircles:
		case GeoPlayground.MakeInt:
		case GeoPlayground.MakePoints:
		case GeoPlayground.MakePerps:
		case GeoPlayground.MakeMdPt:
		case GeoPlayground.HideObject:
		case GeoPlayground.LabelObject:
		case GeoPlayground.FixObject:
		case GeoPlayground.MeasureDist:
		case GeoPlayground.MeasureArea:
		case GeoPlayground.MeasureCirc:
		case GeoPlayground.MakeBisect:
		case GeoPlayground.MeasureAngle:
			for (int i=0;i<clickedList.size();i++) {
			  colorSet(g,clickedList.get(i),true);
			  clickedList.get(i).draw(g,SZ,true);
			}
			if (potentialClick!=null) {colorSet(g,potentialClick,true);potentialClick.draw(g,SZ,true);}
			break;
		}
		if (fixedObject!=null) {
			if (fixedObject!=potentialClick) g.setColor(Color.gray);
			else g.setColor(new Color(220,220,0));
			fixedObject.draw(g,SZ,false);
		}
		if (geometry.getCurvature()==0 && GeoPlayground.model==2) {
			g.setColor(Color.white);
			g.fillOval(SZ-1,SZ-1,3,3);
		}
	}

	public void colorSet(Graphics g, GeoConstruct a, boolean isNew) {
		if (isNew && a.getType()<0) g.setColor(new Color(255,127,127));
		else if (a.getType()<0) g.setColor(Color.red);
		else if (isNew && a.getType()==0) g.setColor(new Color(127,191,127));
		else if (a.getType()==0) g.setColor(new Color(0,127,0));
		else if (isNew && a.getType()<30) g.setColor(new Color(127,127,255));
		else if (a.getType()<30) g.setColor(Color.blue);
		else if (isNew) g.setColor(Color.gray);
		else g.setColor(Color.black);
	}
	public void drawAllConstructs(Graphics g, boolean isNew){
		for (int i=0;i<list.size();i++)
			if ((list.get(i).getValidNew() && isNew) ||
				(list.get(i).getValid() && !isNew))
			if (list.get(i).getShown())
			if (list.get(i).getType()>=30 && isNew) {	// measures are hard to read when the
				double[] v0={0,0,0}, v1={0,0,0};		// new measure is atop the old, hence
				list.get(i).getXYZ(v0);					//
				list.get(i).getNewXYZ(v1);				// if the measure has changed
				if (MathEqns.norm(v0,v1)<.01) {			// but its placement hasn't moved
					g.setColor(new Color(230,230,230));	// we erase
					list.get(i).draw(g,SZ,false);		// the old measure
				}										//
				colorSet(g,list.get(i),isNew);			// we draw the
				list.get(i).draw(g,SZ,isNew);			// new measure
			}											//
			else if (list.get(i).getType()>0){
				colorSet(g,list.get(i),isNew);
				list.get(i).draw(g,SZ,isNew);
			}
		for (int i=0;i<list.size();i++)
			if ((list.get(i).getValidNew() && isNew) ||
					(list.get(i).getValid() && !isNew))
			if (list.get(i).getShown()) 
			if (list.get(i).getType()<=0){
				colorSet(g,list.get(i),isNew);
				list.get(i).draw(g,SZ,isNew);
			}
	}
	public void translateAll() {
		for (int i=0;i<list.size();i++)
			if(list.get(i).getType()>0)
				list.get(i).translate(dragStart,dragNow);
			else list.get(i).update();
	}
	public void getPotentialAny(double[] v1){
		potentialClick=null;
		getPotentialPointOrInt(v1);
		if (potentialClick==null) getPotentialComposite(v1);
	}
	public void getPotentialComposite(double[] v1){
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()<=0)
				if (list.get(i).getShown() && list.get(i).getValid()) 
					if (!clickedList.contains(list.get(i))) {
						if ((list.get(i).mouseIsOver(v1,SZ)) && !clickedList.contains(list.get(i))){
							potentialClick=list.get(i);
						}
					}
	}
	public void getPotentialLine(double[] v1){
		potentialClick=null;
		for (int i=list.size()-1;i>=0;i--)
			if (list.get(i).getType()<0)
				if (list.get(i).getShown() && list.get(i).getValid()) 
					if (!clickedList.contains(list.get(i))) {
						if ((list.get(i).mouseIsOver(v1,SZ)) && !clickedList.contains(list.get(i))){
							potentialClick=list.get(i);
						}
					}
	}
	public void getPotentialCircle(double[] v1){
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()==0)
				if (list.get(i).getShown()) 
					if (!clickedList.contains(list.get(i)) && list.get(i).getValid())
						if ((list.get(i).mouseIsOver(v1,SZ)) && !clickedList.contains(list.get(i)))
								potentialClick=list.get(i);
	}
	public void getPotentialPointOrMeasure(double[] v1){
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()==POINT ||
				list.get(i).getType()==PTonLINE ||
				list.get(i).getType()==PTonCIRC ||
				list.get(i).getType()>30)
				if (list.get(i).getShown() && list.get(i).getValid())
					if (list.get(i).mouseIsOver(v1, SZ)) 
						if (!clickedList.contains(list.get(i)))
							potentialClick=list.get(i);
	}
	public void getPotentialPointOrInt(double[] v1) {
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()>0 && list.get(i).getType()<30)
				if (list.get(i).getShown() && list.get(i).getValid()) 
					if (!clickedList.contains(list.get(i)))
						if (list.get(i).mouseIsOver(v1, SZ))
							potentialClick=list.get(i);
	}
	public void getPotentialPointOrIntOrMeasure(double[] v1) {
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()>0)
				if (list.get(i).getShown() && list.get(i).getValid())
					if (list.get(i).mouseIsOver(v1, SZ)) 
						if (!clickedList.contains(list.get(i)))
							potentialClick=list.get(i);
	}
	public void getPotentialMeasure(double[] v1) {
		potentialClick=null;
		for (int i=0;i<list.size();i++)
			if (list.get(i).getType()>30 && list.get(i).getType()<36)
				if (list.get(i).getShown() && list.get(i).getValid())
					if (list.get(i).mouseIsOver(v1,SZ))
						if (!clickedList.contains(list.get(i)))
							potentialClick=list.get(i);
	}

	public void addChangeListener(ChangeListener e) {geometryListener=e;}

	public void mousePressed(MouseEvent arg0) {
		vector1=geometry.convertMousetoCoord(arg0,SZ);
		Cursor fingerCursor = new Cursor(Cursor.HAND_CURSOR),
		defaultCursor= new Cursor(Cursor.DEFAULT_CURSOR);
		setCursor(defaultCursor); 
		if(geometry.mouseIsValid(vector1)) {
			alreadyMoving=true;
			switch(GeoPlayground.whatToDo){ 
			case GeoPlayground.Move:
				for (int i=0;i<3;i++) dragStart[i]=vector1[i];
				if(potentialClick!=null){
					if(geometry.mouseIsValid(vector1))
						setCursor(fingerCursor); 
					clickedList.clear();
					clickedList.add(potentialClick);
				}
				//else{// potentialClick==null
					//for (int i=0;i<3;i++) dragStart[i]=vector1[i];
				//}
				break;
			}
		}
		repaint();
	}


	public void mouseMoved(MouseEvent arg0) {// if the mouse is moved
		alreadyMoving=false;
		vector1=geometry.convertMousetoCoord(arg0,SZ);
		Cursor defaultCursor= new Cursor(Cursor.DEFAULT_CURSOR);
		setCursor(defaultCursor);
		if (geometry.mouseIsValid(vector1)) switch (GeoPlayground.whatToDo) {
		case GeoPlayground.FixObject:
			getPotentialAny(vector1);
			break;
		case GeoPlayground.MeasureDist:
		case GeoPlayground.MakeCircles:
			getPotentialPointOrInt(vector1);
			break;
		case GeoPlayground.MakeLines:
		case GeoPlayground.MakeSegment:
		case GeoPlayground.MakeMdPt:
		case GeoPlayground.MeasureAngle:
		case GeoPlayground.MakeBisect:
			getPotentialPointOrInt(vector1);
			if (clickedList.size()>0 && potentialClick!=null && geometry.getCurvature()==1) {
			  clickedList.getLast().getXYZ(vector1);				// this stops the user
			  potentialClick.getXYZ(vector2);						// from creating lines
			  double dist=0;										// between antipodes in
			  for (int j=0;j<3;j++) dist+=(vector1[j]+vector2[j]);	// S (&P)
			  if (Math.abs(dist)<.0001) potentialClick=null;		//
			}
			break;
		case GeoPlayground.MakePoints:
			getPotentialComposite(vector1);
			break;
		case GeoPlayground.MakeInt:
			getPotentialComposite(vector1);
			break;
		case GeoPlayground.MeasureArea:
		case GeoPlayground.MeasureCirc:
			getPotentialCircle(vector1);
			break;
		case GeoPlayground.MeasureRatio:
			getPotentialMeasure(vector1);
			break;
		case GeoPlayground.MakePerps:          
			if (clickedList.size()==0) getPotentialLine(vector1);
			else getPotentialPointOrInt(vector1);
			if (clickedList.size()==1 && potentialClick!=null && geometry.getCurvature()==1) {
				clickedList.get(0).getXYZ(vector1);			// this stops user from creating
				potentialClick.getXYZ(vector2);				// perps to line through its polar
				if (Math.abs(MathEqns.dotProduct(vector1,vector2))>.9999)// pts in S & P
					potentialClick=null;								 // geometries
			}
			break;
		case GeoPlayground.Move:
			if (fixedObject==null) getPotentialPointOrMeasure(vector1);
			else potentialClick=null;
			break;
		case GeoPlayground.LabelObject:
			getPotentialPointOrInt(vector1);
			if (potentialClick==null) getPotentialComposite(vector1);
			break;
		case GeoPlayground.HideObject:
			getPotentialPointOrIntOrMeasure(vector1);
			if (potentialClick==null) getPotentialComposite(vector1);
			break;
		}
		else potentialClick=null;
		if (potentialClick!=lastPotential) {
			lastPotential=potentialClick;
			repaint();
		}
	} 

	public void mouseDragged(MouseEvent arg0) {// if the mouse is dragged
		potentialClick=null;
		vector1=geometry.convertMousetoCoord(arg0,SZ);
		Cursor fingerCursor = new Cursor(Cursor.HAND_CURSOR),
		defaultCursor= new Cursor(Cursor.DEFAULT_CURSOR);
		setCursor(defaultCursor);
		if (geometry.mouseIsValid(vector1)) switch (GeoPlayground.whatToDo) {
		case GeoPlayground.Move:
			if (fixedObject==null) {
				if (clickedList.size()>0) {
					clickedList.get(0).setNewXYZ(vector1);
					clickedList.get(0).update();
					LinkedList<GeoConstruct> tempList=new LinkedList<GeoConstruct>();
					tempList.add(clickedList.get(0));
					for (int i=clickedList.get(0).getID()+1;i<list.size();i++) {
					  for(int j=0;j<tempList.size();j++)
						  if(list.get(i).constList.contains(tempList.get(j)))
							 {tempList.add(list.get(i));break;}
					}
					for (int i=0;i<tempList.size();i++) {
						boolean nowValid=true;
						for (int j=0;j<tempList.get(i).getSize();j++) {
							nowValid=(nowValid && tempList.get(i).get(j).getValidNew());
						}
						if (nowValid) {tempList.get(i).setValidNew(true);tempList.get(i).update();}
						else tempList.get(i).setValidNew(false);
					}
				}
				else if (alreadyMoving){
					setCursor(fingerCursor);
				for (int i=0;i<3;i++) dragNow[i]=vector1[i];
				boolean axisNotExist=true;
				for (int i=0;i<3;i++) if (dragStart[i]!=dragNow[i]) axisNotExist=false;
				if (!axisNotExist) translateAll();
				break;
				}
			}
			else {// fixedObject!=null
				for (int i=0;i<3;i++) dragNow[i]=vector1[i];
				for (int i=0;i<list.size();i++)
					if (list.get(i).getType()>0)
						list.get(i).transform(fixedObject,dragStart,dragNow);
				for (int i=0;i<list.size();i++)
					if (list.get(i).getType()<=0)
						list.get(i).update();
			}
		}
		else {
			for (int i=0;i<list.size();i++) {
				list.get(i).getXYZ(vector2);
				list.get(i).setNewXYZ(vector2);
			}
		}
		repaint();
	}

	public void mouseReleased(MouseEvent arg0) {// if the mouse is released
		alreadyMoving=false;
		vector1=geometry.convertMousetoCoord(arg0,SZ);
		Cursor defaultCursor= new Cursor(Cursor.DEFAULT_CURSOR);
		setCursor(defaultCursor);
		if (geometry.mouseIsValid(vector1)) switch (GeoPlayground.whatToDo) {
		case GeoPlayground.Move:
			for (int i=0;i<list.size();i++) {
				if (list.get(i).getValidNew()) {
				  list.get(i).getNewXYZ(vector2);
				  list.get(i).setXYZ(vector2);
				}
				list.get(i).setValid(list.get(i).getValidNew());
			}
			clickedList.clear();
			break;			
		}
		else{
			potentialClick=null;
			clickedList.clear();
			for (int i=0;i<list.size();i++) {
				list.get(i).getXYZ(vector2);
				list.get(i).setNewXYZ(vector2);
			}
		}
		for (int i=0;i<3;i++) {dragStart[i]=dragNow[i];}
		repaint();
	}

	public void mouseEntered(MouseEvent arg0) {}// if the mouse enters

	public void mouseExited(MouseEvent arg0) {// if the mouse exits
		for (int i=0;i<list.size();i++) {
			list.get(i).getXYZ(vector1);
			list.get(i).setNewXYZ(vector1);
		}
		alreadyMoving=false;
		potentialClick=null;        // anything it was doing is dropped
		clickedList.clear();        // 
		repaint();                  // the screen is repainted.
	} 

	public void mouseClicked(MouseEvent arg0) { // if the mouse is clicked
		vector1=geometry.convertMousetoCoord(arg0,SZ);
		Cursor defaultCursor= new Cursor(Cursor.DEFAULT_CURSOR);
		setCursor(defaultCursor);
		if (potentialClick==null) clickedList.clear();
		if (geometry.mouseIsValid(vector1)) switch (GeoPlayground.whatToDo) {
		case GeoPlayground.FixObject:
			getPotentialAny(vector1);
			fixedObject=potentialClick;
			potentialClick=null;
			break;
		case GeoPlayground.MakePoints:
		default:
			getPotentialComposite(vector1);
			if (clickedList.isEmpty()&&potentialClick!=null){
				clickedList.add(potentialClick);
				if(potentialClick.getType()==0)
					clickedList.add(geometry.createPoint(GeoConstruct.PTonCIRC,clickedList,vector1));
				else if(potentialClick.getType()<0)
					clickedList.add(geometry.createPoint(GeoConstruct.PTonLINE,clickedList,vector1));
			}
			else{
				clickedList.add(geometry.createPoint(GeoConstruct.POINT,clickedList,vector1));	
			}
			list.addLast(clickedList.getLast());
			list.getLast().setID(list.size()-1);
			list.getLast().update();
			list.getLast().getNewXYZ(vector1);
			list.getLast().setXYZ(vector1);
			clickedList.clear();
			break;
		case GeoPlayground.MakeMdPt:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) {
				if (clickedList.get(0).getID()>potentialClick.getID()) {
					GeoConstruct temp=clickedList.get(0);
					clickedList.set(0,potentialClick);
					clickedList.add(temp);
				}
				else {
					clickedList.add(potentialClick);
				}
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					// check to see if the midpoint already exists, if not, create it.
					if (list.get(k).getType()==MIDPT)
						if (list.get(k).constList.containsAll(clickedList))
						{alreadyExists=true;list.get(k).setShown(true);}
				}
				if (!alreadyExists) {
					list.addLast(geometry.createPoint(MIDPT,clickedList,vector1));
					list.getLast().setID(list.size()-1);
					list.getLast().update();
					list.getLast().getNewXYZ(vector1);
					list.getLast().setXYZ(vector1);
				}
				clickedList.clear();
			}
			break;
		case GeoPlayground.MeasureCirc:
		  if (potentialClick!=null) {
		    boolean alreadyExists=false;
		    for (int k=0;k<list.size();k++) {
			  if (list.get(k).getType()==CIRCUMF && list.get(k).get(0)==potentialClick)
			    {alreadyExists=true;list.get(k).setShown(true);}
			}
			if (!alreadyExists) {
			  clickedList.addLast(potentialClick);
			  potentialClick.setLabelShown(true);
			  list.addLast(geometry.createPoint(CIRCUMF,clickedList,vector1));
			  list.getLast().setID(list.size()-1);
			  list.getLast().update();
			  list.getLast().getNewXYZ(vector1);
			  list.getLast().setXYZ(vector1);
			}
			clickedList.clear();
		  }
		  break;
		case GeoPlayground.MeasureArea:
		  if (potentialClick!=null) {
		    boolean alreadyExists=false;
		    for (int k=0;k<list.size();k++) {
			  if (list.get(k).getType()==AREA && list.get(k).get(0)==potentialClick)
			    {alreadyExists=true;list.get(k).setShown(true);}
			}
			if (!alreadyExists) {
			  clickedList.addLast(potentialClick);
			  potentialClick.setLabelShown(true);
			  list.addLast(geometry.createPoint(AREA,clickedList,vector1));
			  list.getLast().setID(list.size()-1);
			  list.getLast().update();
			  list.getLast().getNewXYZ(vector1);
			  list.getLast().setXYZ(vector1);
			}
			clickedList.clear();
		  }
		  break;
		case GeoPlayground.MeasureDist:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) 
			if (potentialClick!=clickedList.get(0)) {
				if (clickedList.get(0).getID()>potentialClick.getID()) {
					GeoConstruct temp=clickedList.get(0);
					clickedList.set(0,potentialClick);
					clickedList.add(temp);
				}
				else {
					clickedList.add(potentialClick);
				}
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					// check to see if the distance already exists, if not, create it.
					if (list.get(k).getType()==DISTANCE)
						if (list.get(k).get(0).get(0)==clickedList.get(0) && list.get(k).get(0).get(1)==clickedList.get(1))
						{alreadyExists=true;list.get(k).setShown(true);}
				}
				if (!alreadyExists) {
				  boolean lineExists=false;
				  int lineNumber=list.size();
				  for (int k=0;k<list.size();k++) {
				    if (list.get(k).getType()==LINE || list.get(k).getType()==SEGMENT)
					if (list.get(k).get(0)==clickedList.get(0))
					if (list.get(k).get(1)==clickedList.get(1))
					  {lineExists=true; lineNumber=k;}
				  }
				    if (!lineExists) {
					  list.addLast(geometry.createLine(SEGMENT,clickedList));
					  list.getLast().setID(list.size()-1);
					  list.getLast().update();
					  list.getLast().setShown(false);
					}
					clickedList.clear();
					clickedList.add(list.get(lineNumber));
					list.addLast(geometry.createPoint(DISTANCE,clickedList,vector1));
					list.getLast().setID(list.size()-1);
					list.getLast().update();
					list.getLast().getNewXYZ(vector1);
					list.getLast().setXYZ(vector1);
					list.getLast().get(0).get(0).setLabelShown(true);
					list.getLast().get(0).get(1).setLabelShown(true);
				}
				clickedList.clear();
			}
			break;
		case GeoPlayground.MeasureRatio:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) 
			if (potentialClick!=clickedList.get(0)) {
				clickedList.add(potentialClick);
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					// check to see if the ratio already exists, if not, create it.
					if (list.get(k).getType()==RATIO)
						if (list.get(k).get(0).get(0)==clickedList.get(0) && list.get(k).get(0).get(1)==clickedList.get(1))
						{alreadyExists=true;list.get(k).setShown(true);}
				}
				if (!alreadyExists) {
					list.addLast(geometry.createPoint(RATIO,clickedList,vector1));
				  	list.getLast().setID(list.size()-1);
				}
				clickedList.clear();
			}
			break;
		case GeoPlayground.MeasureAngle:
			if (clickedList.size()<2 && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null && potentialClick!=clickedList.get(0)) {
			  if (clickedList.get(0).getID()>potentialClick.getID()) {
				GeoConstruct temp=clickedList.get(0);
				clickedList.set(0,potentialClick);
				clickedList.add(temp);
			  }
			  else{
				clickedList.add(potentialClick);
			  } 
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++)
					if (list.get(k).getType()==ANGLE)
					if (list.get(k).get(0).get(0)==clickedList.get(0))
					if (list.get(k).get(0).get(1)==clickedList.get(1))
					if (list.get(k).get(0).get(2)==clickedList.get(2))
							{alreadyExists=true;list.get(k).setShown(true);}
				if (!alreadyExists) {
				  boolean lineExists=false;
				  int lineNumber=list.size();
				  for (int k=0;k<list.size();k++) {
				    if (list.get(k).getType()==BISECTOR)
					if (list.get(k).get(0)==clickedList.get(0))
					if (list.get(k).get(1)==clickedList.get(1))
					if (list.get(k).get(2)==clickedList.get(2))
					  {lineExists=true; lineNumber=k;}
				  }
				  if (!lineExists) {
					list.addLast(geometry.createLine(BISECTOR,clickedList));
					list.getLast().setID(list.size()-1);
					list.getLast().update();
					list.getLast().getNewXYZ(vector2);
					list.getLast().setXYZ(vector2);
					list.getLast().setShown(false);
				  }
				    clickedList.clear();
					clickedList.add(list.get(lineNumber));
					list.add(geometry.createPoint(ANGLE,clickedList,vector1));
					list.getLast().setID(list.size()-1);
					list.getLast().update();
					list.getLast().getNewXYZ(vector1);
					list.getLast().setXYZ(vector1);
					list.getLast().get(0).get(0).setLabelShown(true);
					list.getLast().get(0).get(1).setLabelShown(true);
					list.getLast().get(0).get(2).setLabelShown(true);
				}
				clickedList.clear();
			}
			
			break;
		case GeoPlayground.MakeBisect:
			if (clickedList.size()<2 && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null && potentialClick!=clickedList.get(0)) {
			  if (clickedList.get(0).getID()>potentialClick.getID()) {
					GeoConstruct temp=clickedList.get(0);
					clickedList.set(0,potentialClick);
					clickedList.add(temp);
				}
				else{
					clickedList.add(potentialClick);
				}
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++)
					if (list.get(k).getType()==BISECTOR)
					if (list.get(k).get(0)==clickedList.get(0) &&
						list.get(k).get(1)==clickedList.get(1) &&
						list.get(k).get(2)==clickedList.get(2))
							{alreadyExists=true;list.get(k).setShown(true);}
				if (!alreadyExists) {
					list.add(geometry.createLine(BISECTOR,clickedList));
					list.getLast().setID(list.size()-1);
					list.getLast().update();
					list.getLast().getNewXYZ(vector1);
					list.getLast().setXYZ(vector1);
				}
				clickedList.clear();
			}
			break;
		case GeoPlayground.MakeLines:
		case GeoPlayground.MakeSegment:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) {
				if (clickedList.get(0).getID()>potentialClick.getID()) {
					GeoConstruct temp=clickedList.get(0);
					clickedList.set(0,potentialClick);
					clickedList.add(temp);
				}
				else{
					clickedList.add(potentialClick);
				}
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					if ((list.get(k).getType()==LINE && GeoPlayground.whatToDo==GeoPlayground.MakeLines) ||
							(list.get(k).getType()==SEGMENT && GeoPlayground.whatToDo==GeoPlayground.MakeSegment))
						if (list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==clickedList.get(1))
							{alreadyExists=true; list.get(k).setShown(true);}
					if (list.get(k).getType()==LINE && GeoPlayground.whatToDo==GeoPlayground.MakeSegment)
						if (list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==clickedList.get(1))  {
							alreadyExists=true;
							list.add(k,geometry.createLine(SEGMENT, clickedList));
							list.get(k).setID(k);
							for (int l=k+1;l<list.size();l++) {				//
								for (int m=0;m<list.get(l).getSize();m++) {	//
									if (list.get(l).get(m)==list.get(k+1))	//
										list.get(l).set(m,list.get(k));		//
								}											//
							}												//
							if (fixedObject==list.get(k+1)) fixedObject=list.get(k);
							list.remove(k+1);
							/*if (geometry.getCurvature()==2)*/ {
								LinkedList<GeoConstruct> tempList=new LinkedList<GeoConstruct>();
								for (int l=k+1;l<list.size();l++)
									if ((list.get(l).getType()==PTonLINE && list.get(l).get(0)==list.get(k)) ||
										((list.get(l).getType()>=LINEintLINE0 && list.get(l).getType()<=CIRCintLINE1 &&
										(list.get(l).get(0)==list.get(k) || list.get(l).get(1)==list.get(k)))))
											tempList.add(list.get(k));
								if (tempList.size()>0) {
									for (int l=tempList.get(0).getID();l<list.size();l++)
										for (int m=0;m<tempList.get(0).getSize();m++)
											if (tempList.contains(list.get(l).get(m)))
												tempList.add(list.get(l));
									for (int l=0;l<tempList.size();l++) {
										tempList.get(l).update();
										tempList.get(l).getNewXYZ(vector1);
										tempList.get(l).setXYZ(vector1);
										tempList.get(l).setValid(tempList.get(l).getValidNew());
									}
								}
							}
						}
					if (list.get(k).getType()==SEGMENT && GeoPlayground.whatToDo==GeoPlayground.MakeLines)
						if (list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==clickedList.get(1)) {
							alreadyExists=true;
							list.add(k,geometry.createLine(LINE, clickedList));
							list.get(k).setID(k);
							for (int l=k+1;l<list.size();l++) {				//
								for (int m=0;m<list.get(l).getSize();m++) {	//
									if (list.get(l).get(m)==list.get(k+1))	//
										list.get(l).set(m,list.get(k));		//
								}											//
							}												//
							if (fixedObject==list.get(k+1)) fixedObject=list.get(k);
							list.remove(k+1);
							LinkedList<GeoConstruct> tempList=new LinkedList<GeoConstruct>();
							for (int l=k+1;l<list.size();l++)
								if ((list.get(l).getType()==PTonLINE && list.get(l).get(0)==list.get(k)) ||
									((list.get(l).getType()>=LINEintLINE0 && list.get(l).getType()<=CIRCintLINE1 &&
									(list.get(l).get(0)==list.get(k) || list.get(l).get(1)==list.get(k)))))
										tempList.add(list.get(k));
							if (tempList.size()>0) {
								for (int l=tempList.get(0).getID();l<list.size();l++)
									for (int m=0;m<tempList.get(0).getSize();m++)
										if (tempList.contains(list.get(l).get(m)))
											tempList.add(list.get(l));
								for (int l=0;l<tempList.size();l++) {
									tempList.get(l).update();
									tempList.get(l).getNewXYZ(vector1);
									tempList.get(l).setXYZ(vector1);
									tempList.get(l).setValid(tempList.get(l).getValidNew());
								}
							}
					}
				}
				if (!alreadyExists && clickedList.get(1)!=clickedList.get(0)) {
					if (GeoPlayground.whatToDo==GeoPlayground.MakeLines)
						list.addLast(geometry.createLine(LINE,clickedList));
					else
						list.addLast(geometry.createLine(SEGMENT,clickedList));
					list.getLast().setID(list.size()-1);
				}
				clickedList.clear();
				break;
			}
			break;
		case GeoPlayground.MakeCircles:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) {
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					if (list.get(k).getType()==CIRCLE)
						if (list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==potentialClick)
						{alreadyExists=true; list.get(k).setShown(true);}
				}
				if (!alreadyExists && clickedList.get(0)!=potentialClick) {
					list.addLast(geometry.createCircle(clickedList.get(0), potentialClick)); 
					list.getLast().setID(list.size()-1);
				}
				clickedList.clear();
				break;
			}
			break;
		case GeoPlayground.MakeInt:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) {
				if (clickedList.get(0).getID()>potentialClick.getID()) {
					clickedList.addFirst(potentialClick);
				}
				else{
					clickedList.add(potentialClick);
				}
				boolean alreadyExists=false;
				for (int k=0;k<list.size();k++) {
					if (list.get(k).getType()>=LINEintLINE0 && list.get(k).getType()<30)
						if ((list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==clickedList.get(1)) ||
								(list.get(k).get(1)==clickedList.get(0) && list.get(k).get(0)==clickedList.get(1)))
						{alreadyExists=true;list.get(k).setShown(true);}
				}
				if (!alreadyExists) {
					geometry.createIntersections(clickedList.get(0), clickedList.get(1), list);
				}
				clickedList.clear();
				break;
			}
			break;
		case GeoPlayground.MakePerps:
			if (clickedList.isEmpty() && potentialClick!=null) clickedList.add(potentialClick);
			else if (potentialClick!=null) {
				boolean alreadyExists=false;
				clickedList.get(0).getXYZ(vector2);					// keeps the
				potentialClick.getXYZ(binorm);						// user from
				MathEqns.crossProduct(vector2,binorm,norm);			// making P & S
				if (Math.abs(MathEqns.dotProduct(norm,norm))<.01)	// illegal lines
					alreadyExists=true;								// (08_06_03)
				for (int k=0;k<list.size();k++) {
					if (list.get(k).getType()<0);
					if(list.get(k).constList.size()==2)
					if (list.get(k).get(0)==clickedList.get(0) && list.get(k).get(1)==potentialClick)
					{alreadyExists=true;list.get(k).setShown(true);}
				}
				if (!alreadyExists) {
					clickedList.add(potentialClick);
					list.addLast(geometry.createLine(PERP,clickedList));
					list.getLast().update();
					list.getLast().getNewXYZ(vector1); 
					list.getLast().setXYZ(vector1);
					list.getLast().setID(list.size()-1);
				}
				clickedList.clear();
				break;
			}
			break;
		case GeoPlayground.HideObject:
			if (potentialClick!=null) {
				potentialClick.setShown(false);
				if (potentialClick==fixedObject) fixedObject=null;
			}
			break;
		case GeoPlayground.LabelObject:
			if (potentialClick!=null) 
				potentialClick.setLabelShown(!potentialClick.getLabelShown());
			break;
		case GeoPlayground.Move:
			break;
		}
		potentialClick=null;
		lastPotential=null;
		repaint();
	}

}